#include <{{ declr["hdr_fname"] }}>

{% for ent in declr["ents"] if ent["kind"] == "g" -%}
const char *
{{ ent["name"] }}_str(enum {{ ent["name"] }} obj)
{
	switch (obj) {
	{% for sym_name, sym_name_short in ent["members"] -%}
	case {{ sym_name }}:
		return "{{ sym_name_short }}";
	{% endfor -%}
	}

	return "ENOSYS";
}

{% endfor %}
{% for struct in structs_1 %}
static inline int
{% if '_yaml' is in struct["name"] and struct["yaml_args"] -%}
{{ struct["name"] }}(FILE *stream,{% for (args,type) in struct["yaml_args"].items() -%} {{ type }} {{ args }} {%- if loop.last %}{% else %}, {%endif %}{%- endfor -%})
{%- else -%}
{{ struct["name"] }}_yaml(FILE *stream, const {{ struct["name"] }} *{{ struct["obj"] }}, int indent, const char *sep, int head)
{%- endif %}
{
	int wrtn = 0;

	if (head) {
		wrtn += fprintf(stream, "%*s{{ struct["name"] }}:", indent, "");
		indent += 2;
	}
	if (!obj) {
		wrtn += fprintf(stream, " ~");
		return wrtn;
	}
	if (head) {
		wrtn += fprintf(stream, "\n");
	}
	{% for field ,fmt in struct["members"].items() -%}
        {% if fmt is not mapping and fmt.endswith("_str") -%}
	wrtn += fprintf(stream, "%*s{{ field }}: %s%s",
                        indent, "", {{ fmt }}({{ struct["obj"] }}->{{ field }}), {% if loop.last %}""{% else %}sep{% endif %});

	{%- elif '?' is in field %}
        wrtn += fprintf(stream, "%*s{{ field.split('?')[0]}}: {{ fmt.mem_fmt }}%s",
                        indent, "", ({{ fmt.cond }}) ? "{{ fmt.opt_1 }}" : "{{ fmt.opt_2 }}", {% if loop.last %}""{% else %}sep{% endif %});

        {%- elif fmt is mapping %}
        wrtn += fprintf(stream, "%*s{{ field }}:{ {% for (mem_field,mem_fmt) in fmt.items() -%}{{ mem_field }}: {{ mem_fmt }}{% if loop.last %}}%s",{% else %}, {% endif %}
                        {%- endfor %}
                        indent, "",
                        ({% for (mem_field,mem_fmt) in fmt.items() -%}
                              {{ struct["obj"] }}->{{ field }}.{{ mem_field }}{% if loop.last %}, sep);{% else %}, {% endif %}
                        {%- endfor %}

	{%- elif fmt == "%*s" %}
	wrtn += fprintf(stream, "%*s{{ field }}: {{ fmt }}%s",
                        indent, "", {{ struct["name"].split('_descr')[0] }}_state_str({{ struct["obj"] }}->{{ field }}), {% if loop.last %}""{% else %}sep{% endif %});

	{%- elif 'XNVME' is in fmt %}
        wrtn += fprintf(stream, "%*s{{ field }}: '{{ fmt }}'",
                        indent, "", XNVME{{ fmt.split('XNVME')[1].split('_FMT')[0] }}_TO_STR({{ struct["obj"] }}->{{ field }}), {% if loop.last %}""{% else %}sep{% endif %}); 

	{%- else %}
        wrtn += fprintf(stream, "%*s{{ field }}: {{ fmt }}%s",
                        indent, "", {{ struct["obj"] }}->{{ field }}, {% if loop.last %}""{% else %}sep{% endif %});
        {%- endif -%}
	{%- endfor %}

	return wrtn;
}
{% if '_yaml' is not in struct["name"] %}
int
{{ struct["name"] }}_fpr(FILE *stream, const struct {{ struct["name"] }} *{{ struct["obj"] }}, int opts)
{
	int wrtn = 0;

	switch (opts) {
	case XNVME_PR_TERSE:
		wrtn += fprintf(stream, "# ENOSYS: opts(0x%x)", opts);
		return wrtn;

	case XNVME_PR_DEF:
	case XNVME_PR_YAML:
		break;
	}

	wrtn += {{ struct["name"] }}_yaml(stream, {{ struct["obj"] }}, 0, "\n", 1);
	wrtn += fprintf(stream, "\n");

	return wrtn;
}

int
{{ struct["name"] }}_pr(const struct {{ struct["name"] }} *{{ struct["obj"] }}, int opts)
{
        return {{ struct["name"] }}_fpr(stdout, {{ struct["obj"] }}, opts);
}
{% endif %}
{% endfor %}

{%- for struct in structs_2 -%}
int
{{ struct["name"] }}_fpr(FILE *stream, {% for (args,type) in struct["arguments"].items() -%} {{ type }} {{ args }} {%- if loop.last %}{% else %}, {%endif %}{%- endfor -%})
{
        int wrtn = 0;
	{%- if struct["intial"] %}
	{{  struct["intial"].descr }}
	{% endif %}
	switch (opts) {
        case XNVME_PR_TERSE:
                wrtn += fprintf(stream, "# ENOSYS: opts(0x%x)", opts);
                return wrtn;

        case XNVME_PR_DEF:
        case XNVME_PR_YAML:
                break;
        }

	wrtn += fprintf(stream, "{{ struct["name"] }}:");

        if (!{{ struct["obj"] }}) {
                wrtn += fprintf(stream, " ~\n");
                return wrtn;
        }

	{%- if struct["switch"] %}
        switch ({{ struct["switch"] }}) {
        {%- endif %}

	wrtn += fprintf(stream, "\n");
        {% for field ,fmt in struct["members"].items() -%}
	{%- if struct["switch"] -%}
        {%- if '(' is not in field and fmt == None -%}
        case {{ field }}:

	{%- elif 'default' is in field -%}
        {{ field.split('(')[0] }}:
                 wrtn += fprintf(stream, " { {%- for (mem_field,mem_fmt) in fmt.items() -%}{{ mem_field }}: {{mem_fmt }}," {{ field.split('(')[1].split(')')[0] }})
                         {%- endfor %}
        }

	{%- elif '(' is in field and fmt != None %}
        case {{ field.split('(')[0] }}:
                 wrtn += fprintf(stream, "  {{ struct["obj"] }}: { {%- for (mem_field,mem_fmt) in fmt.items() -%}{{ mem_field }}: {{ mem_fmt }}{%- if loop.last %}}\n",                                            {% else %}, {%endif %}{%- endfor -%}
                        {%- for (mem_field,mem_fmt) in fmt.items() %}
                        {{ struct["obj"] }}.{{ field.split('(')[1].split(')')[0] }}.{{ mem_field }}
                        {%- if loop.last -%});{% else %}, {% endif %}
                        {%- endfor %}
                 break;

	{%- elif fmt is mapping %}
	case {{ field }}:
	{%- for (mem_field, mem_fmt) in fmt.items() %}
	{%- if '[]' is in mem_field %}
		for (int i = 0; i < {{ mem_field.split(']')[1] }}; ++i) {
			{%- if 'XNVME' is in mem_fmt %}
			wrtn += fprintf(stream, "  {{ mem_fmt }}\n", XNVME_I32_TO_STR({{ mem_field.split('[')[0] }}[i]));
			{%- else %}
                        wrtn += fprintf(stream, "  {{ mem_fmt }}\n", {{ mem_field.split('[')[0] }}[i]);
			{%- endif %}
                }
		break;
	{%- else %}
		{%- if mem_fmt is mapping %}
		{%- for (mem_field_2, mem_fmt_2) in mem_fmt.items() %}
		wrtn += fprintf(stream, "  {{ mem_field_2 }}: {{ mem_fmt_2 }}\n", {{ struct["obj"] }}->{{ mem_field }}.{{ mem_field_2 }};
		{%- endfor %}
		{%- else %}
		{%- if 'cdw' is in mem_field %}
		wrtn += fprintf(stream, "  {{ mem_field }}: {{ mem_fmt }}\n", {{ mem_field }};
		{%- else %}
		wrtn += fprintf(stream, "  {{ mem_field }}: {{ mem_fmt }}\n", {{ struct["obj"] }}->{{ mem_field }};
		{%- endif %}
		{%- endif %}
	{%- endif -%}
	{%- endfor %}
	{%- endif %}

	{% elif 'add_info' is in field %}

	{{ fmt }}

	{%- elif ':' is in fmt and '[]' is in field %}
        wrtn += fprintf(stream, "  {{ field.split('[')[0] }}: {{ fmt.split(':')[0]}}\n",
                        {{ fmt.split(':')[1] }}({{ struct["obj"] }}->{{ field.split('[')[0] }}, {{ field.split(']')[1] }}));

	{%- elif '[]' is in field %}
	{%- if field.split(']')[1]|int != 0 and  (( field.split(']')[1]|int  <= 4 and '/' is not in field) and 'yaml' is not in field) %}
	wrtn += fprintf(stream, "  {{ field.split('[')[0] }}: [{% for i in  range(field.split(']')[1]|int) %}{{ fmt }}{% if loop.last %}]\n", {% else %}, {%endif %}{%- endfor -%}
	{%- for i in range(field.split(']')[1]|int) -%}
        {{ struct["obj"] }}->{{ field.split('[')[0] }}[{{i}}]{% if loop.last %});{% else %}, {% endif %}{%- endfor -%}

	{%- else %}
	{%- if '/' is in field and (fmt is mapping and 'yaml' is not in field)  %}
	wrtn += fprintf(stream, "  {{ field.split('[')[0] }}:\n");
        for (int i = 0; i < {{ field.split(']')[1].split('/')[0] }}; ++i) {
		{%- if 'info' in fmt %}
		{{ fmt.info }} 
		{% endif -%}
                wrtn += fprintf(stream, "  - { {%- for (mem_field,mem_fmt) in fmt.items() %}
			{%- if 'info' is not in mem_field -%}
			{{ mem_field }}: {{ mem_fmt }}{%- if loop.last %}}\n", {% else %}, {% endif %}{%- endif -%}{%- endfor -%}
                        {%- for (mem_field,mem_fmt) in fmt.items() %}
			{%- if 'info' is not in mem_field -%}
                        {{ struct["obj"] }}->{{ field.split('[')[0] }}[i].{{ mem_field }}
                        {%- if loop.last -%});{% else %}, {% endif %}
                        {% endif %}
			{%- endfor %}
	}

	{% elif fmt is mapping and 'yaml' is in field %}

	for (int i = 0; i < {{ field.split('[')[0] }}; ++i) {

		wrtn += fprintf(stream, "  - {");
		{%- for (mem_field, list) in fmt.items() %}
		{% if 'info' in mem_field -%}
		{{ list }}
		{%- else -%}
		wrtn += {{ mem_field }}({%- for list_mem in list %}{{ list_mem }}{%- if loop.last -%}{% else %}, {% endif %}{%- endfor %});
		{%- endif %}
		{%- endfor %}
                wrtn += fprintf(stream, "}\n");

	}

	{%- elif fmt is mapping %}
	wrtn += fprintf(stream, "  {{ field.split('[')[0] }}:\n");
	for (int i = 0; i < {{ field.split(']')[1] }}; ++i) {
                wrtn += fprintf(stream, "  - { {%- for (mem_field,mem_fmt) in fmt.items() -%}{{ mem_field }}: {{ mem_fmt }}{%- if loop.last %}}\n", {% else %}, {%endif %}{%- endfor -%}
                        {%- for (mem_field,mem_fmt) in fmt.items() %}
			{{ struct["obj"] }}->{{ field.split('[')[0] }}[i].{{ mem_field }}
			{%- if loop.last -%});{% else %}, {% endif %}
			{%- endfor -%}
        }
	{%- else %}
	for (int i = 0; i < {{ field.split(']')[1] }}; ++i) {
		wrtn += fprintf(stream, "  {{ field.split('[')[0] }}: {{ fmt }}\n",
                        {{ struct["obj"] }}->{{ field.split('[')[0] }}[i]);
	}
	{%- endif -%}
	{%- endif -%}

	{%- elif '{}' is in field and 'yaml' is in field %}
	{%- for (mem_field, list) in fmt.items() %}
	{% if 'info' in mem_field -%}
        {{ list }}
        {%- else -%}
        wrtn += {{ mem_field }}({%- for list_mem in list %}{{ list_mem }}{%- if loop.last -%}{% else %}, {% endif %}{%- endfor %});
        {%- endif %}
	wrtn += fprintf(stream, "\n");
        {% endfor %}

	{%- elif ':' is in fmt and 'XNVME_SPEC' is in fmt %}
	wrtn += fprintf(stream, "  {{ field }}: {{ fmt.split(':')[0] }}\n",
			XNVME_MIN({{ fmt.split(':')[1] }},
				  strlen((const char *){{ struct["obj"] }}->{{ field }}, {{ fmt.split(':')[1] }}
                        ), {{ struct["obj"] }}->{{ field }});

	{%- elif fmt is mapping and fmt.mem_val and fmt.mem_fmt %}
        wrtn += fprintf(stream, "  {{ field }}:{{ fmt.mem_fmt }}\n", {{ fmt.mem_val }});

	{%- elif 'none' is in fmt %}
	wrtn += fprintf(stream, "  {{ field }}:\n");

	{%- elif fmt is mapping and '[]' is not in field %}
        wrtn += fprintf(stream, " {{ field }}:{");
	{% for (mem_field,mem_fmt) in fmt.items() -%}
	wrtn += fprintf(stream, " {{ mem_field }}: {{ mem_fmt }},", {{ struct["obj"] }}->{{ field }}.{{ mem_field }});
	{% if loop.last %}wrtn += fprintf(stream, "}\n");
	{% else %}{% endif %}
        {%- endfor %}

	{%- else %}
        wrtn += fprintf(stream, "  {{ field }}: {{ fmt }}\n",
			{{ struct["obj"] }}->{{ field }});
        {%- endif -%}
	{%- endfor %}

        return wrtn;
}

int
{{ struct["name"] }}_pr({% for (args,type) in struct["arguments"].items() -%} {{ type }} {{ args }} {%- if loop.last %}{% else %}, {%endif %}{%- endfor -%})
{
        return {{ struct["name"] }}_fpr(stdout, {% for (args,type) in struct["arguments"].items() -%} {{ args }} {%- if loop.last %}{% else %}, {%endif %}{%- endfor -%} );
}
{% endfor %}
